<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <!-- 设置文档字符编码和视口 -->
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <!-- 页面标题 -->
    <title>自由落体实验</title>
    <!-- 引入外部样式表和字体 -->
    <link rel="stylesheet" href="/css/style.css">
    <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap" rel="stylesheet">
    <style>
        /* 定义Material Design 3颜色系统 */
        :root {
            --md-sys-color-primary: #6750A4;        /* 主色调 */
            --md-sys-color-on-primary: #FFFFFF;     /* 主色调上的文字颜色 */
            --md-sys-color-primary-container: #EADDFF; /* 主色调容器背景 */
            --md-sys-color-on-primary-container: #21005E; /* 主色调容器上的文字颜色 */
            --md-sys-color-surface: #FEF7FF;        /* 页面背景色 */
            --md-sys-color-on-surface: #1D1B20;     /* 页面文字颜色 */
            --md-sys-color-surface-variant: #E7E0EC; /* 表面变体颜色 */
            --md-sys-color-on-surface-variant: #49454F; /* 表面变体上的文字颜色 */
            --md-sys-color-outline: #79747E;        /* 轮廓线颜色 */
            --md-sys-color-error: #B3261E;          /* 错误提示颜色 */
            --md-sys-color-success: #4CAF50;        /* 成功提示颜色 */
        }

        /* 基础页面样式 */
        body {
            font-family: 'Roboto', sans-serif;      /* 使用Roboto字体 */
            margin: 0;                              /* 移除默认边距 */
            padding: 0;                             /* 移除默认内边距 */
            background-color: var(--md-sys-color-surface); /* 设置背景色 */
            color: var(--md-sys-color-on-surface);  /* 设置文字颜色 */
            min-height: 100vh;                      /* 最小高度为视口高度 */
        }

        /* 主容器样式 */
        .container {
            max-width: 1200px;                      /* 最大宽度限制 */
            margin: 0 auto;                         /* 水平居中 */
            padding: 2rem;                          /* 内边距 */
        }

        /* 页头样式 */
        .header {
            text-align: center;                     /* 文字居中 */
            margin-bottom: 3rem;                    /* 底部外边距 */
        }

        .header h1 {
            font-size: 2.5rem;                      /* 标题字体大小 */
            font-weight: 500;                       /* 字体粗细 */
            color: var(--md-sys-color-on-surface);  /* 标题颜色 */
            margin-bottom: 1rem;                    /* 底部外边距 */
            letter-spacing: -0.5px;                 /* 字间距 */
        }

        .header p {
            font-size: 1.1rem;                      /* 段落字体大小 */
            color: var(--md-sys-color-on-surface-variant); /* 段落文字颜色 */
            max-width: 600px;                       /* 最大宽度 */
            margin: 0 auto;                         /* 水平居中 */
            line-height: 1.6;                       /* 行高 */
        }

        /* 内容区域布局 */
        .content {
            display: grid;                          /* 使用网格布局 */
            grid-template-columns: 1fr 1fr;         /* 两列等宽 */
            gap: 2rem;                              /* 列间距 */
            align-items: start;                     /* 顶部对齐 */
        }

        /* 响应式设计：移动端布局 */
        @media (max-width: 768px) {
            .content {
                grid-template-columns: 1fr;         /* 单列布局 */
            }
        }

        /* 表单容器样式 */
        .form-container {
            background-color: var(--md-sys-color-surface); /* 背景色 */
            border-radius: 1.5rem;                  /* 圆角 */
            padding: 2rem;                          /* 内边距 */
            box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1); /* 阴影效果 */
            border: 1px solid var(--md-sys-color-surface-variant); /* 边框 */
            display: flex;                          /* 弹性布局 */
            flex-direction: column;                 /* 垂直排列 */
            gap: 1.5rem;                           /* 元素间距 */
        }

        /* 表单组样式 */
        .form-group {
            margin-bottom: 0;                       /* 移除底部外边距 */
        }

        .form-group label {
            display: block;                         /* 块级显示 */
            font-size: 1rem;                        /* 字体大小 */
            font-weight: 500;                       /* 字体粗细 */
            color: var(--md-sys-color-on-surface);  /* 文字颜色 */
            margin-bottom: 0.5rem;                  /* 底部外边距 */
        }

        .form-group input {
            width: 100%;                           /* 宽度100% */
            padding: 0.75rem 1rem;                 /* 内边距 */
            border: 1px solid var(--md-sys-color-outline); /* 边框 */
            border-radius: 0.75rem;                /* 圆角 */
            font-size: 1rem;                       /* 字体大小 */
            color: var(--md-sys-color-on-surface); /* 文字颜色 */
            background-color: var(--md-sys-color-surface); /* 背景色 */
            transition: border-color 0.3s ease;    /* 过渡效果 */
            box-sizing: border-box;                /* 盒模型计算方式 */
        }

        .form-group input:focus {
            outline: none;                         /* 移除默认轮廓 */
            border-color: var(--md-sys-color-primary); /* 聚焦时边框颜色 */
        }

        /* 按钮容器样式 */
        .buttons {
            display: flex;                         /* 弹性布局 */
            gap: 1rem;                             /* 按钮间距 */
            margin-top: 0;                         /* 顶部外边距 */
            margin-bottom: 1rem;                   /* 底部外边距 */
        }

        /* 按钮基础样式 */
        .button {
            flex: 1;                               /* 等宽分布 */
            padding: 0.875rem 1.5rem;              /* 内边距 */
            border: none;                          /* 移除边框 */
            border-radius: 1.5rem;                 /* 圆角 */
            font-size: 0.875rem;                   /* 字体大小 */
            font-weight: 500;                      /* 字体粗细 */
            cursor: pointer;                       /* 鼠标指针样式 */
            transition: all 0.3s ease;             /* 过渡效果 */
            text-transform: uppercase;             /* 大写字母 */
            letter-spacing: 0.5px;                 /* 字间距 */
            text-align: center;                    /* 文字居中 */
            text-decoration: none;                 /* 移除下划线 */
            box-sizing: border-box;                /* 盒模型计算方式 */
        }

        /* 主要按钮样式 */
        .button-primary {
            background-color: var(--md-sys-color-primary); /* 背景色 */
            color: var(--md-sys-color-on-primary); /* 文字颜色 */
        }

        /* 次要按钮样式 */
        .button-secondary {
            background-color: var(--md-sys-color-surface-variant); /* 背景色 */
            color: var(--md-sys-color-on-surface-variant); /* 文字颜色 */
        }

        /* 按钮悬停效果 */
        .button:hover {
            opacity: 0.9;                          /* 透明度 */
            transform: translateY(-2px);           /* 上移效果 */
        }

        /* 结果容器样式 */
        .result-container {
            background-color: var(--md-sys-color-surface); /* 背景色 */
            border-radius: 1.5rem;                 /* 圆角 */
            padding: 2rem;                         /* 内边距 */
            box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1); /* 阴影效果 */
            border: 1px solid var(--md-sys-color-surface-variant); /* 边框 */
            margin-top: 0;                         /* 顶部外边距 */
        }

        /* 结果项样式 */
        .result-item {
            display: flex;                         /* 弹性布局 */
            justify-content: space-between;        /* 两端对齐 */
            padding: 0.75rem 0;                    /* 内边距 */
            border-bottom: 1px solid var(--md-sys-color-surface-variant); /* 底部边框 */
            align-items: center;                   /* 垂直居中 */
        }

        .result-item:last-child {
            border-bottom: none;                   /* 最后一项移除底部边框 */
        }

        /* 结果标签样式 */
        .result-label {
            color: var(--md-sys-color-on-surface-variant); /* 文字颜色 */
            flex: 1;                               /* 占据剩余空间 */
        }

        /* 结果值样式 */
        .result-value {
            font-weight: 500;                      /* 字体粗细 */
            color: var(--md-sys-color-on-surface); /* 文字颜色 */
            margin-left: 1rem;                     /* 左侧外边距 */
            text-align: right;                     /* 文字右对齐 */
            min-width: 100px;                      /* 最小宽度 */
        }

        /* 动画容器样式 */
        .animation-container {
            background-color: var(--md-sys-color-surface); /* 背景色 */
            border-radius: 1.5rem;                 /* 圆角 */
            padding: 2rem;                         /* 内边距 */
            box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1); /* 阴影效果 */
            border: 1px solid var(--md-sys-color-surface-variant); /* 边框 */
            aspect-ratio: 16/9;                    /* 宽高比 */
            position: relative;                    /* 相对定位 */
            overflow: hidden;                      /* 溢出隐藏 */
            min-height: 400px;                     /* 最小高度 */
        }

        /* 画布样式 */
        canvas {
            width: 100%;                          /* 宽度100% */
            height: 100%;                         /* 高度100% */
            background-color: var(--md-sys-color-surface); /* 背景色 */
        }

        /* 返回按钮样式 */
        .back-button {
            display: inline-block;                 /* 行内块级显示 */
            margin-top: 2rem;                      /* 顶部外边距 */
            padding: 0.875rem 1.5rem;              /* 内边距 */
            background-color: var(--md-sys-color-surface-variant); /* 背景色 */
            color: var(--md-sys-color-on-surface-variant); /* 文字颜色 */
            text-decoration: none;                 /* 移除下划线 */
            border-radius: 1.5rem;                 /* 圆角 */
            font-weight: 500;                      /* 字体粗细 */
            transition: all 0.3s ease;             /* 过渡效果 */
        }

        /* 返回按钮悬停效果 */
        .back-button:hover {
            background-color: var(--md-sys-color-surface-variant); /* 背景色 */
            opacity: 0.9;                          /* 透明度 */
            transform: translateY(-2px);           /* 上移效果 */
        }

        /* 移动端响应式样式 */
        @media (max-width: 768px) {
            .form-container {
                padding: 1.5rem;                   /* 减小内边距 */
            }

            .animation-container {
                min-height: 300px;                 /* 减小最小高度 */
            }

            .buttons {
                flex-direction: column;            /* 垂直排列按钮 */
            }

            .button {
                width: 100%;                       /* 按钮宽度100% */
            }
        }
    </style>
</head>
<body>
    <!-- 主容器 -->
    <div class="container">
        <!-- 页头 -->
        <div class="header">
            <h1>自由落体实验</h1>
            <p>研究物体在重力作用下的自由下落运动，计算下落时间、速度和能量变化</p>
        </div>

        <!-- 内容区域 -->
        <div class="content">
            <!-- 表单容器 -->
            <div class="form-container">
                <form id="freefallForm">
                    <!-- 高度输入组 -->
                    <div class="form-group">
                        <label for="height">初始高度 (m)</label>
                        <input type="number" id="height" name="height" th:value="${height}" min="0.1" max="100" step="0.1" value="10" required>
                    </div>
                    <!-- 按钮组 -->
                    <div class="buttons">
                        <button type="button" id="calculateBtn" class="button button-primary">计算落体时间</button>
                        <button type="button" id="animateBtn" class="button button-secondary">播放动画</button>
                    </div>
    </form>

                <!-- 结果容器 -->
                <div class="result-container" id="resultContainer" style="display: none;">
                    <h3>计算结果</h3>
                    <div class="result-item">
                        <span class="result-label">下落时间</span>
                        <span class="result-value" id="timeResult">0.0 s</span>
                    </div>
                    <div class="result-item">
                        <span class="result-label">落地速度</span>
                        <span class="result-value" id="velocityResult">0.0 m/s</span>
                    </div>
                    <div class="result-item">
                        <span class="result-label">重力势能</span>
                        <span class="result-value" id="potentialEnergyResult">0.0 J</span>
                    </div>
                    <div class="result-item">
                        <span class="result-label">动能</span>
                        <span class="result-value" id="kineticEnergyResult">0.0 J</span>
                    </div>
                </div>
    </div>

            <!-- 动画容器 -->
    <div class="animation-container">
                <canvas id="freefallCanvas"></canvas>
            </div>
        </div>

        <!-- 返回按钮 -->
        <a href="/" class="back-button">返回主页</a>
    </div>

    <script th:inline="javascript">
        // 获取CSS变量的辅助函数
        const getColor = (varName) => {
            return getComputedStyle(document.documentElement).getPropertyValue(varName).trim();
        };

        // 获取画布和上下文
        const canvas = document.getElementById('freefallCanvas');
        const ctx = canvas.getContext('2d');
        let animationId = null;                    // 动画ID
        let isAnimating = false;                   // 动画状态标志
        let currentHeight = 10;                    // 当前高度
        let mass = 1.0;                           // 物体质量(kg)
        const g = 9.8;                            // 重力加速度(m/s²)
        let timeScale = 0.5;                      // 时间缩放因子

        // 调整画布大小以适应容器
        function resizeCanvas() {
            const container = canvas.parentElement;
            canvas.width = container.clientWidth - 20;  // 减去padding
            canvas.height = container.clientHeight - 20;
        }

        // 绘制场景
        function drawScene() {
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            
            const padding = 40;                    // 内边距
            const groundY = canvas.height - padding; // 地面Y坐标
            const maxHeight = canvas.height - 2 * padding; // 最大高度
            const scaleFactor = maxHeight / currentHeight; // 缩放因子
            
            // 绘制背景和地面
            ctx.fillStyle = getColor('--md-sys-color-surface');
            ctx.fillRect(0, 0, canvas.width, canvas.height);
            
            // 绘制高度刻度
            const scaleStep = Math.max(1, Math.ceil(currentHeight / 10)); // 刻度步长
            ctx.strokeStyle = getColor('--md-sys-color-on-surface-variant');
            ctx.fillStyle = getColor('--md-sys-color-on-surface-variant');
            ctx.font = '12px Roboto';
            ctx.textAlign = 'right';
            
            // 绘制刻度线和数值
            for (let h = 0; h <= currentHeight; h += scaleStep) {
                const y = groundY - h * scaleFactor;
                if (y >= padding) {
                    ctx.beginPath();
                    ctx.moveTo(padding - 5, y);
                    ctx.lineTo(padding, y);
                    ctx.stroke();
                    ctx.fillText(h + ' m', padding - 10, y + 4);
                }
            }
            
            // 绘制垂直线
            ctx.beginPath();
            ctx.moveTo(padding, padding);
            ctx.lineTo(padding, groundY);
            ctx.stroke();
            
            // 绘制地面
            ctx.beginPath();
            ctx.moveTo(0, groundY);
            ctx.lineTo(canvas.width, groundY);
            ctx.lineWidth = 2;
            ctx.strokeStyle = getColor('--md-sys-color-outline');
            ctx.stroke();
            
            // 绘制球体
            ctx.beginPath();
            ctx.arc(canvas.width / 2, padding, 20, 0, Math.PI * 2);
            ctx.fillStyle = getColor('--md-sys-color-primary');
            ctx.fill();
            
            // 绘制文字标签
            ctx.fillStyle = getColor('--md-sys-color-on-surface');
            ctx.font = '16px Roboto';
            ctx.textAlign = 'center';
            ctx.fillText('高度: ' + currentHeight.toFixed(1) + ' m', canvas.width / 2, padding - 30);
        }

        // 动画函数
        function animateFall() {
            if (isAnimating) {
                cancelAnimationFrame(animationId);
                isAnimating = false;
                document.getElementById('animateBtn').textContent = '播放动画';
                drawScene();
                return;
            }
            
            isAnimating = true;
            document.getElementById('animateBtn').textContent = '停止动画';
            
            // 计算物理参数
            const fallTime = Math.sqrt(2 * currentHeight / g); // 下落时间
            const startTime = Date.now();
            const padding = 40;
            const groundY = canvas.height - padding;
            const maxHeight = canvas.height - 2 * padding;
            const scaleFactor = maxHeight / currentHeight;
            
            // 动画循环
            function animate() {
                if (!isAnimating) return;
                
                const elapsedTime = (Date.now() - startTime) / 1000 * timeScale;
                const progress = Math.min(elapsedTime / fallTime, 1);
                
                // 计算下落距离
                const fallenDistance = 0.5 * g * Math.pow(elapsedTime, 2);
                const currentPosition = Math.min(fallenDistance, currentHeight);
                
                // 清除画布
                ctx.clearRect(0, 0, canvas.width, canvas.height);
                
                // 绘制背景和地面
                ctx.fillStyle = getColor('--md-sys-color-surface');
                ctx.fillRect(0, 0, canvas.width, canvas.height);
                
                // 绘制高度刻度
                const scaleStep = Math.max(1, Math.ceil(currentHeight / 10));
                ctx.strokeStyle = getColor('--md-sys-color-on-surface-variant');
                ctx.fillStyle = getColor('--md-sys-color-on-surface-variant');
                ctx.font = '12px Roboto';
                ctx.textAlign = 'right';
                
                // 绘制刻度线和数值
                for (let h = 0; h <= currentHeight; h += scaleStep) {
                    const y = groundY - h * scaleFactor;
                    if (y >= padding) {
                        ctx.beginPath();
                        ctx.moveTo(padding - 5, y);
                        ctx.lineTo(padding, y);
                        ctx.stroke();
                        ctx.fillText(h + ' m', padding - 10, y + 4);
                    }
                }
                
                // 绘制垂直线
                ctx.beginPath();
                ctx.moveTo(padding, padding);
                ctx.lineTo(padding, groundY);
                ctx.stroke();
                
                // 绘制地面
                ctx.beginPath();
                ctx.moveTo(0, groundY);
                ctx.lineTo(canvas.width, groundY);
                ctx.lineWidth = 2;
                ctx.strokeStyle = getColor('--md-sys-color-outline');
                ctx.stroke();
                
                // 绘制物体当前位置
                const ballY = padding + currentPosition * scaleFactor;
                
                ctx.beginPath();
                ctx.arc(canvas.width / 2, ballY, 20, 0, Math.PI * 2);
                ctx.fillStyle = getColor('--md-sys-color-primary');
                ctx.fill();
                
                // 绘制文字标签
                const remainingHeight = currentHeight - currentPosition;
                ctx.fillStyle = getColor('--md-sys-color-on-surface');
                ctx.font = '16px Roboto';
                ctx.textAlign = 'center';
                ctx.fillText('剩余高度: ' + remainingHeight.toFixed(1) + ' m', canvas.width / 2, ballY - 30);
                
                // 继续动画或结束
                if (progress < 1) {
                animationId = requestAnimationFrame(animate);
                } else {
                    // 添加落地后的弹跳效果
                    setTimeout(() => {
                        // 小弹跳
                        ctx.clearRect(0, 0, canvas.width, canvas.height);
                        
                        // 重新绘制背景和地面
                        ctx.fillStyle = getColor('--md-sys-color-surface');
                        ctx.fillRect(0, 0, canvas.width, canvas.height);
                        
                        // 绘制高度刻度
                        const scaleStep = Math.max(1, Math.ceil(currentHeight / 10));
                        ctx.strokeStyle = getColor('--md-sys-color-on-surface-variant');
                        ctx.fillStyle = getColor('--md-sys-color-on-surface-variant');
                        ctx.font = '12px Roboto';
                        ctx.textAlign = 'right';
                        
                        // 绘制刻度线和数值
                        for (let h = 0; h <= currentHeight; h += scaleStep) {
                            const y = groundY - h * scaleFactor;
                            if (y >= padding) {
                                ctx.beginPath();
                                ctx.moveTo(padding - 5, y);
                                ctx.lineTo(padding, y);
                                ctx.stroke();
                                ctx.fillText(h + ' m', padding - 10, y + 4);
                            }
                        }
                        
                        // 绘制垂直线
                        ctx.beginPath();
                        ctx.moveTo(padding, padding);
                        ctx.lineTo(padding, groundY);
                        ctx.stroke();
                        
                        // 绘制地面
                        ctx.beginPath();
                        ctx.moveTo(0, groundY);
                        ctx.lineTo(canvas.width, groundY);
                        ctx.lineWidth = 2;
                        ctx.strokeStyle = getColor('--md-sys-color-outline');
                        ctx.stroke();
                        
                        // 绘制球体（稍微压扁）
                        ctx.beginPath();
                        ctx.ellipse(canvas.width / 2, groundY - 10, 25, 15, 0, 0, Math.PI * 2);
                        ctx.fillStyle = getColor('--md-sys-color-primary');
                        ctx.fill();
                        
                        // 恢复原始状态
                        setTimeout(() => {
                            drawScene();
                            isAnimating = false;
                            document.getElementById('animateBtn').textContent = '播放动画';
                        }, 300);
                    }, 100);
                }
            }
            
            animate();
        }

        // 计算物理参数
        function calculatePhysics(height) {
            const fallTime = Math.sqrt(2 * height / g); // 下落时间
            const finalVelocity = g * fallTime;         // 最终速度
            const potentialEnergy = mass * g * height;  // 势能
            const kineticEnergy = 0.5 * mass * Math.pow(finalVelocity, 2); // 动能
            
            return {
                time: fallTime,
                velocity: finalVelocity,
                potentialEnergy: potentialEnergy,
                kineticEnergy: kineticEnergy
            };
        }

        // 页面加载和窗口大小变化事件监听
        window.addEventListener('load', function() {
            resizeCanvas();
            drawScene();
            
            // 设置初始值
            const heightInput = document.getElementById('height');
            
            if (!heightInput.value) heightInput.value = currentHeight;
            
            // 实时更新预览
            heightInput.addEventListener('input', function() {
                const height = parseFloat(heightInput.value) || currentHeight;
                
                currentHeight = height;
                drawScene();
            });
        });
        
        window.addEventListener('resize', function() {
            resizeCanvas();
            drawScene();
        });

        // 计算按钮点击事件
        document.getElementById('calculateBtn').addEventListener('click', function() {
            const height = parseFloat(document.getElementById('height').value);
            
            const results = calculatePhysics(height);
            
            // 更新结果显示
            document.getElementById('timeResult').textContent = results.time.toFixed(2) + ' s';
            document.getElementById('velocityResult').textContent = results.velocity.toFixed(2) + ' m/s';
            document.getElementById('potentialEnergyResult').textContent = results.potentialEnergy.toFixed(2) + ' J';
            document.getElementById('kineticEnergyResult').textContent = results.kineticEnergy.toFixed(2) + ' J';
            
            document.getElementById('resultContainer').style.display = 'block';
            
            currentHeight = height;
            
            drawScene();
        });

        // 动画按钮点击事件
        document.getElementById('animateBtn').addEventListener('click', function() {
            animateFall();
        });

        // 初始绘制
        const initialHeight = /*[[${height}]]*/ 10;
        
        currentHeight = initialHeight;
        
        // 页面加载时自动调整画布大小
        if (document.readyState === 'complete') {
            resizeCanvas();
            drawScene();
        } else {
            window.addEventListener('load', function() {
                resizeCanvas();
                drawScene();
            });
        }
    </script>
</body>
</html>